package com.acmedcare.framework.exchange.center.core.json;

import com.acmedcare.framework.exchange.center.core.PluginMetadata;
import com.acmedcare.framework.exchange.center.core.metadata.IDataApplication;
import com.acmedcare.framework.exchange.center.core.metadata.PluginEntity;
import com.acmedcare.framework.exchange.center.core.metadata.PluginEntityScan;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import xyz.vopen.cartier.classpathscanner.FastClasspathScanner;
import xyz.vopen.cartier.classpathscanner.scanner.ScanResult;

@Slf4j
public class DefaultExtensionConvert implements IPluginExtensionConvert {

  final ObjectMapper objectMapper;

  public DefaultExtensionConvert(ObjectMapper objectMapper) {
    this.objectMapper = objectMapper;
  }

  @Override
  public void registerTypes(PluginMetadata metadata) {

    IDataApplication dataApplication = metadata.getApplicationInstance();
    PluginEntityScan scan;
    try {
       scan = dataApplication.getClass().getAnnotation(PluginEntityScan.class);
    }catch (Exception e){

      log.error(String.format("获取插件信息失败，失败信息:%s",e.getMessage()+e.getStackTrace()),e);
      throw e;
    }

    if (scan == null) {
      return;
    }

    Set<String> packages = new HashSet<>();
    if (scan.value().length > 0) {

      for (String p : scan.value()) {

        packages.add(p);
      }
    }

    if (scan.basePackages().length > 0) {

      for (String p : scan.basePackages()) {

        packages.add(p);
      }
    }

    if (scan.basePackageClasses().length > 0) {
      for (Class c : scan.basePackageClasses()) {

        packages.add(c.getPackage().getName());
      }
    }

    packages.add(dataApplication.getClass().getPackage().getName());
    packages.forEach(p -> {

      FastClasspathScanner fastClasspathScanner = new FastClasspathScanner(
          p);
      fastClasspathScanner.addClassLoader(metadata.getClassLoader());

      ScanResult result = fastClasspathScanner.scan();
      List<Class<?>> types = new ArrayList<Class<?>>();
      result.getNamesOfClassesWithAnnotationsAnyOf(PluginEntity.class).forEach(className -> {

        try {
          types.add(metadata.getClassLoader().loadClass(className));
        } catch (ClassNotFoundException e) {
          log.error("添加插件json转换错误", e);
        }
      });

      objectMapper.registerModule(new PluginSubTypeModule(types.toArray(new Class<?>[0])));
    });
  }
}
